﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace SilverlightSockets.Server
{
	// Listens for connections on port 943 and dispatches requests to a PolicyConnection
	public class PolicyServer : IDisposable
	{
		public const int Port = 943;

		private Socket m_listener;
		private byte[] m_policy;

		// pass in the path of an XML file containing the socket policy
		public PolicyServer(string policyFile)
		{
			// Load the policy file
			m_policy = File.ReadAllBytes(policyFile);

			// Create the Listening Socket
			m_listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);

			// Put the socket into dual mode to allow a single socket 
			// to accept both IPv4 and IPv6 connections
			// Otherwise, server needs to listen on two sockets,
			// one for IPv4 and one for IPv6
			// NOTE: dual-mode sockets are supported on Vista and later
			m_listener.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);

			m_listener.Bind(new IPEndPoint(IPAddress.IPv6Any, Port));
			m_listener.Listen(10);

			m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
		}

		// Called when we receive a connection from a client
		public void OnConnection(IAsyncResult res)
		{
			Socket client = null;

			try
			{
				client = m_listener.EndAccept(res);
			}
			catch (SocketException)
			{
				return;
			}

			Console.WriteLine("Incoming policy file connection.");

			// handle this policy request with a PolicyConnection
			PolicyConnection pc = new PolicyConnection(client, m_policy);

			// look for more connections
			m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
		}

		public void Close()
		{
			m_listener.Close();
		}

		public void Dispose()
		{
			Close();
		}
	}

	//public class Program
	//{
	//    static void Main(string[] args)
	//    {
	//        string PolicyFile = (args.Length == 0) ? "PolicyFile.xml" : args[0];
	//        if (args.Length == 0)
	//        {
	//            Console.WriteLine("No policy file specified; using PolicyFile.xml");
	//        }

	//        PolicyServer ps = new PolicyServer(PolicyFile);
	//        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
	//    }
	//}
}
